import queue
import threading
import time

"""
使用Threading模块创建线程
使用Threading模块创建线程，直接从threading.Thread继承，然后重写__init__方法和run方法
"""

exitFlag = 0


class MyThread(threading.Thread):
    def __init__(self, threadId, name, counter):
        threading.Thread.__init__(self)
        self.threadId = threadId
        self.name = name
        self.counter = counter

    def run(self):
        print('Starting ' + self.name)
        print_time(self.name, self.counter, 5)
        print('Exiting ' + self.name)


def print_time(threadName, delay, counter):
    while counter:
        if exitFlag:
            (threading.Thread).exit()
        time.sleep(delay)
        print('%s : %s' % (threadName, time.ctime(time.time())))
        counter -= 1


threadLock = threading.Lock()
threads = []

"""
线程同步
使用Thread对象的Lock和Rlock可以实现简单的线程同步，这两个对象都有acquire方法和release方法，
对于那些需要每次只允许一个线程操作的数据，可以将其操作放到acquire和release方法之间。
"""


class LockMyThread(MyThread):
    def __init__(self, threadId, name, counter):
        super().__init__(threadId, name, counter)

    def run(self):
        print('Starting ' + self.name)
        print('加锁：' + self.name + str(threadLock.acquire()))  # 加锁
        print_time(self.name, self.counter, 3)
        threadLock.release()
        print('释放锁')
        print('Exiting ' + self.name)


"""
线程优先级队列(Queue)
Python的Queue模块中提供了同步的、线程安全的队列类，包括FIFO（先入先出)队列Queue，LIFO（后入先出）队列LifoQueue，和优先级队列PriorityQueue。
这些队列都实现了锁原语，能够在多线程中直接使用。可以使用队列来实现线程间的同步。
常用方法：
    Queue.qsize() 返回队列的大小
    Queue.empty() 如果队列为空，返回True,反之False
    Queue.full() 如果队列满了，返回True,反之False
    Queue.full 与 maxsize 大小对应
    Queue.get([block[, timeout]])获取队列，timeout等待时间
    Queue.get_nowait() 相当Queue.get(False)
    Queue.put(item, block=True, timeout=None) 写入队列，timeout等待时间
    Queue.put_nowait(item) 相当 Queue.put(item, False)
    Queue.task_done() 在完成一项工作之后，Queue.task_done()函数向任务已经完成的队列发送一个信号
    Queue.join() 实际上意味着等到队列为空，再执行别的操作
"""


class QueueMyThread(threading.Thread):
    def __init__(self, threadId, name, q):
        threading.Thread.__init__(self)
        self.threadId = threadId
        self.name = name
        self.q = q

    def run(self):
        print('Starting ' + self.name)
        process_data(self.name, self.q)
        print('Exiting ' + self.name)


def process_data(threadName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            queueLock.release()
            print('%s processing %s' % (threadName, data))
        else:
            queueLock.release()
        time.sleep(1)


threadList = ['Thread-1', 'Thread-2', 'Thread-3']
nameList = ['One', 'Two', 'Three', 'Four', 'Five']
queueLock = threading.Lock()
workQueue = queue.Queue(10)
threadQueues = []
threadId = 1

if __name__ == "__main__":
    for tName in threadList:
        thread = QueueMyThread(threadId, tName, workQueue)
        thread.start()
        threadQueues.append(thread)
        threadId += 1

    queueLock.acquire()
    for word in nameList:
        workQueue.put(word)
    queueLock.release()
    while not workQueue.empty():
        pass
    exitFlag = 1
    for t in threadQueues:
        t.join()
    print('Exiting Main Thread')

# 自定义线程
# MyThread(1, 'Thread-1', 1).start()
# MyThread(2, 'Thread-2', 2).start()
#
# 锁
# thread1 = LockMyThread(1, 'Thread-1', 1)
# thread2 = LockMyThread(2, 'Thread-2', 2)
# thread1.start()
# thread2.start()
# threads.append(thread1)
# threads.append(thread2)
# for t in threads:
#     t.join()
# print('Exiting Main Thread')
